#include <am.h>
#include <klib.h>
#include <klib-macros.h>

#define FB_ADDR 0x1C000000
#define VGA_CTRL_ADDR 0x10002000
#define VGA_FB_ADDR 0x81000000
#define VGA_REG_CTRL *((volatile uint32_t *)(VGA_CTRL_ADDR))
#define VGA_REG_BASE *((volatile uint32_t *)(VGA_CTRL_ADDR + 4))
#define VGA_REG_OFST *((volatile uint32_t *)(VGA_CTRL_ADDR + 8))

#define VGA_H 800
#define VGA_W 600

int main()
{
    putstr("[config VGA module]\n");
    // VGA_REG_CTRL = 0;
    // VGA_REG_BASE = VGA_FB_ADDR;
    // VGA_REG_OFST = VGA_FB_ADDR - FB_ADDR;
    *(uint32_t *)(VGA_CTRL_ADDR) = 0;
    *(uint32_t *)(VGA_CTRL_ADDR + 4) = VGA_FB_ADDR;
    *(uint32_t *)(VGA_CTRL_ADDR + 8) = VGA_FB_ADDR - FB_ADDR;

    volatile uint32_t write_mode = *(uint32_t *)(VGA_CTRL_ADDR);
    printf("mode: %d\n", write_mode);
    volatile uint32_t write_base = *(uint32_t *)(VGA_CTRL_ADDR + 4);
    printf("base: %x\n", write_base);
    volatile uint32_t write_ofst = *(uint32_t *)(VGA_CTRL_ADDR + 8);
    printf("offset: %x\n", write_ofst);
    putstr("[config done]\n");

    uint64_t *mem_data = (void *)(VGA_FB_ADDR);
    for(int i = 0; i < 50; ++i){    
        printf("[mem data] addr: %p val: %lx\n", mem_data + i, mem_data[i]);
    }

    putstr("[write fb]\n");
    mem_data = (void *)(VGA_FB_ADDR);
    for(int i = 0; i < VGA_H * VGA_W / 8; ++i){
        mem_data[i] = 0x00F0F0F000F0F0F0L;
    }
    putstr("[write fb done]\n");

    mem_data = (void *)(VGA_FB_ADDR);
    for(int i = 0; i < 50; ++i){    
        printf("[mem data] addr: %p val: %lx\n", mem_data + i, mem_data[i]);
    }

    // putstr("[write fb]\n");
    // uint64_t *fb = (void *)FB_ADDR;
    // for(int i = 0; i < VGA_H * VGA_W; ++i) {
    //     fb[i] = 0x123456;
    // }

    // mem_data = (void *)(VGA_FB_ADDR);
    // for(int i = 0; i < VGA_H * VGA_W; ++i){
    //     printf("[mem data] addr: %p val: %lx\n", mem_data + i, mem_data[i]);
    // }
    
    return 0;
}
